#include <QDebug>
#include "irm_datamodel.h"
using namespace std;

namespace ophies {



const char* DataModel::ATTRS_PATIENT[PAITNET_ATTR_COUNT] = { "patient_key",
                                            "patient_id_value",
                                            "patient_name",
                                            "patient_sex",
                                            "patient_birth_dttm",
                                            "related_patient_key",
                                            "created_dttm",
                                            "deleted_dttm",
                                            "url"};
const char* DataModel::ATTRS_DCM_STUDY[ATTR_DCM_STUDY_COUNT] = {  "dcm_study_key",
                                                "vgroup_key",
                                                "study_instance_uid",
                                                "patient_key",
                                                "patient_id",
                                                "patient_name",
                                                "patient_sex",
                                                "patient_birth_dttm",
                                                "patient_age",
                                                "patient_weight",
                                                "patient_size",
                                                "study_id",
                                                "study_dttm",
                                                "accession_no",
                                                "study_desc",
                                                "study_size",
                                                "series_count",
                                                "instance_count",
                                                "created_dttm",
                                                "updated_dttm",
                                                "deleted_dttm",
                                                "url"};
const char* DataModel::ATTRS_DCM_SERIES[ATTR_DCM_SERIES_COUNT] = {"dcm_series_key",
                                                "vgroup_key",
                                                "series_instance_uid",
                                                "dcm_study_key",
                                                "modality",
                                                "series_no",
                                                "series_dttm",
                                                "series_desc",
                                                "bodypart",
                                                "series_size",
                                                "instance_count",
                                                "created_dttm",
                                                "deleted_dttm",
                                               "url"};
const char* DataModel::ATTRS_DCM_INSTANCE[ATTR_DCM_INSTANCE_COUNT] = {
                                                "dcm_instance_key",
                                               "vgroup_key",
                                               "sop_instance_uid",
                                               "sop_class_uid",
                                               "dcm_series_key",
                                               "dcm_study_key",
                                               "instance_no",
                                               "content_dttm",
                                               "instance_size",
                                               "created_dttm",
                                               "deleted_dttm",
                                               "url"};

const char* DataModel::ATTRS_DOCSET[ATTR_DOCSET_COUNT] = {"docset_key",
                                         "vgroup_key",
                                         "vgroup_id",
                                         "vgroup_id_type",
                                         "vgroup_name",
                                         "docset_uid",
                                         "docset_class_uid",
                                         "docset_group_uid",
                                         "filter_key",
                                         "filter_uid",
                                         "filter_class_uid",
                                         "filter_name",
                                         "patient_key",
                                         "patient_id_value",
                                         "patient_name",
                                         "docset_created_dttm",
                                         "docset_deleted_dttm",
                                         "xds_docset_key",
                                         "metadata_xml",
                                         "docset_uuid",
                                         "source_id",
                                         "content_type_code_value",
                                         "content_type_coding_scheme",
                                         "content_type_code_meaning",
                                         "docset_status",
                                         "docset_title",
                                         "docset_comments",
                                         "submit_dttm",
                                         "xds_docset_created_dttm",
                                         "xds_docset_deleted_dttm",
                                         "document_count",
                                         "url"};

DataModel::DataModel(DataModelType type, QObject *parent) :
    QObject(parent),
    m_type(type),
    m_attributes(new QHash<QString, QString>())
{
}

DataModel::~DataModel()
{
    delete m_attributes;
}

bool DataModel::save()
{
    onSave();
    return false;
}

void DataModel::onSave()
{

}

/////////////////////////////////////////////////////////////////////////
/// \brief DataModel::fromJson
/// \param value
/////////////////////////////////////////////////////////////////////////
void DataModel::fromJson(Json::Value &value)
{
    Json::Value child_series;
    Json::Value child_instances;
    QString key_series = "dcm_series";
    QString key_instances = "dcm_instances";

    switch(m_type) {
    case PATIENT:
        for(int i = 0; i < PAITNET_ATTR_COUNT; i++)
        {
            setAttr(ATTRS_PATIENT[i],
                                 QString(value.get(ATTRS_PATIENT[i], "error").asString().c_str()));
        }
        break;
    case DCM_STUDY:
        for(int i = 0; i < ATTR_DCM_STUDY_COUNT; i++)
        {
            QString s = QString(value.get(ATTRS_DCM_STUDY[i], "error").asString().c_str());
            // qDebug() << s << ATTRS_DCM_STUDY[i];
            setAttr(ATTRS_DCM_STUDY[i], s);
        }


        child_series = value["dcm_series"];
        if( !child_series.isNull() && child_series.isArray() )
        {
            for(unsigned int i=0; i < child_series.size(); i++)
            {
                DcmSeries* series = new DcmSeries(parent());
                series->fromJson(child_series[i]);
                dynamic_cast<DcmStudy*>(this)->appendSeries(series);
            }
        } else
        {

        }

        break;
    case DCM_SERIES:
        for(int i = 0; i < ATTR_DCM_SERIES_COUNT; i++)
        {
            qDebug() << QString(value.get(ATTRS_DCM_SERIES[i], "error").asString().c_str());
            setAttr(ATTRS_DCM_SERIES[i],
                                 QString(value.get(ATTRS_DCM_SERIES[i], "error").asString().c_str()));

        }

        child_instances = value["dcm_instances"];
        if( !child_instances.isNull() && child_instances.isArray() )
        {
            for(int i=0; i < child_instances.size(); i++)
            {
                DcmInstance* instance = new DcmInstance(parent());
                instance->fromJson(child_instances[i]);
                dynamic_cast<DcmSeries*>(this)->appendInstance(instance);
            }
        } else
        {

        }
        break;
    case DCM_INSTANCE:
        for(int i = 0; i < ATTR_DCM_INSTANCE_COUNT; i++)
        {
            setAttr(ATTRS_DCM_INSTANCE[i],
                                 QString(value.get(ATTRS_DCM_INSTANCE[i], "error").asString().c_str()));

			DcmInstance* me = dynamic_cast<DcmInstance*>(this);
			me->set_download_url(value.get("download_url", "error").asString().c_str());
			me->set_wado_url(value.get("wado_url", "error").asString().c_str());
        }
        break;
    case DOCSET:
        for(int i = 0; i < ATTR_DOCSET_COUNT; i++)
        {
            setAttr(ATTRS_DOCSET[i],
                                 QString(value.get(ATTRS_DOCSET[i], "error").asString().c_str()));
        }
        break;
    default:
        break;
    }

}

QString DataModel::getAttr(QString attr_name, QString defaultValue)
{
    return m_attributes->value(attr_name, defaultValue);
}

void DataModel::setAttr(QString attr_name, QString value)
{
    m_attributes->insert(attr_name, value);
}

DataModelType DataModel::getDataModelType()
{
    return m_type;
}

bool DataModel::equal(DataModel* actual)
{
    if(actual == NULL)
    {
        qDebug() << "data is null. cannot compare. type: " << (int)getDataModelType();
        return false;
    }

    QList<QString> array;

    switch(getDataModelType())
    {
    case DCM_STUDY:
        for(int i = 0; i < ATTR_DCM_STUDY_COUNT; i++)
        {
            array.append(ATTRS_DCM_STUDY[i]);
        }
        break;
    case DCM_SERIES:
        for(int i = 0; i < ATTR_DCM_SERIES_COUNT; i++)
        {
            array.append(ATTRS_DCM_SERIES[i]);
        }
        break;
    case DCM_INSTANCE:
        for(int i = 0; i < ATTR_DCM_INSTANCE_COUNT; i++)
        {
            array.append(ATTRS_DCM_INSTANCE[i]);
        }
        break;
    case DOCSET:
        for(int i = 0; i < ATTR_DOCSET_COUNT; i++)
        {
            array.append(ATTRS_DOCSET[i]);
        }
        break;
    case PATIENT:
//        count = PA;
//        attrs = ATTRS_DCM_STUDY;
        break;
    default:
        break;
    }


    bool ret = true;
    for(int i=0; i<array.size(); i++)
    {
        if(this->getAttr(array[i]) != actual->getAttr(array[i]))
        {
            qDebug() << "ERROR: " << array[i] <<
                        " Expected: " << this->getAttr(array[i], "error expected") <<
                        " Actual: " << actual->getAttr(array[i], "error actual");
            ret = false;
        } else
        {
            qDebug() << array[i]
                        << "Expected: " << this->getAttr(array[i])
                        << "Actual: " << actual->getAttr(array[i]);
        }

    }

    return ret;

}

/// dcm_instances
DcmInstance::DcmInstance(QObject *parent)
:DataModel(ophies::DCM_INSTANCE, parent)
{
}

DcmInstance::~DcmInstance()
{
}

QString DcmInstance::get_download_url()
{
    return download_url;
}

QString DcmInstance::get_wado_url()
{
    return wado_url;
}

void DcmInstance::setParentDcmSeries(DcmSeries *series)
{
    m_parentSeries = series;
}

DcmSeries* DcmInstance::getParentDcmSeries()
{
    return m_parentSeries;
}

void DcmInstance::set_download_url(QString d)
{
	download_url = d;
}

void DcmInstance::set_wado_url(QString w)
{
	wado_url = w;
}

///////////////////////////////////////////////////////////////////////
/// dcm_series
DcmSeries::DcmSeries(QObject *parent)
:DataModel(DCM_SERIES, parent),
  m_dcm_instances(new QList<DcmInstance*>())

{
}

DcmSeries::~DcmSeries()
{
    for(int i = 0; i < m_dcm_instances->size(); i++)
    {
        delete m_dcm_instances->at(i);
    }
    delete m_dcm_instances;
}

void DcmSeries::appendInstance(DcmInstance *i)
{
    m_dcm_instances->append(i);
    i->setParentDcmSeries(this);
}

QList<DcmInstance*>* DcmSeries::getAllDcmInstances()
{
    return m_dcm_instances;
}

DcmInstance* DcmSeries::getDcmInstanceByInstanceKey(QString sop_instance_key)
{
    for(int i=0; i < m_dcm_instances->size(); i++)
    {
        if(m_dcm_instances->at(i)->get_dcm_instance_key() == sop_instance_key)
        {
            return m_dcm_instances->at(i);
        }
    }

    return NULL;
}

DcmInstance* DcmSeries::getDcmInstanceBySopInstanceUid(QString sop_instance_uid)
{
    for(int i=0; i < m_dcm_instances->size(); i++)
    {
        if(m_dcm_instances->at(i)->get_sop_instance_uid() == sop_instance_uid)
        {
            return m_dcm_instances->at(i);
        }
    }

    return NULL;
}

void DcmSeries::setParentDcmStudy(DcmStudy *study)
{
    m_parentStudy = study;
}

DcmStudy* DcmSeries::getParentDcmStudy()
{
    return m_parentStudy;
}

///////////////////////////////////////////////////////////////////////
/// dcm_studies
DcmStudy::DcmStudy(QObject *parent)
    :DataModel(DCM_STUDY, parent),
      m_dcm_series(new QList<DcmSeries*>())
{
}

DcmStudy::~DcmStudy()
{
    for(int i = 0; i < m_dcm_series->size(); i++)
    {
        delete m_dcm_series->at(i);
    }
    delete m_dcm_series;
}

void DcmStudy::appendSeries(DcmSeries *se)
{
    m_dcm_series->append(se);
    se->setParentDcmStudy(this);
}

QList<DcmSeries*>* DcmStudy::getAllDcmSeries()
{
    return m_dcm_series;
}

DcmSeries* DcmStudy::getDcmSeriesBySeriesKey(QString series_key)
{
    for(int i=0; i < m_dcm_series->size(); i++)
    {
        if(m_dcm_series->at(i)->get_dcm_series_key() == series_key)
        {
            return m_dcm_series->at(i);
        }
    }

    return NULL;
}

DcmSeries* DcmStudy::getDcmSeriesBySeriesInstanceUid(QString series_uid)
{
    for(int i=0; i < m_dcm_series->size(); i++)
    {
        if(m_dcm_series->at(i)->get_series_instance_uid() == series_uid)
        {
            return m_dcm_series->at(i);
        }
    }

    return NULL;
}

// docsets
Docset::Docset(QObject *parent)
:DataModel(ophies::DOCSET, parent)
{
}

Docset::~Docset()
{
}

// patients
Patient::Patient(QObject *parent)
:DataModel(PATIENT, parent)
{
}

Patient::~Patient()
{
}






}




